home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / VGAZOOM.ASM < prev    next >
Assembly Source File  |  1989-02-22  |  15KB  |  782 lines

  1. page ,132
  2.  
  3. ;--------------------------------------------------------------------------
  4. ; Filename:     VGAZOOM1.ASM
  5. ; Program name:    VGAZOOM.COM
  6. ;
  7. ; Link with:    VGAZOOM2.OBJ (Hidden mode driver module)
  8. ;
  9. ; Description:    This program demonstrates hidden VGA modes. The program
  10. ;        is a Terminate-And-Stay-Resident module that provides
  11. ;        elementary Video BIOS support for the hidden modes.
  12. ;        Applications that only use MS-DOS function 09h (print 
  13. ;        string) for video output, should work with this program. 
  14. ;
  15. ;        The program traps the Int 10h vector to provide extended
  16. ;        BIOS support. The program also traps int 9h (keyboard), 
  17. ;        to handle detection of Hotkeys for panning and mode 
  18. ;        switching etc.
  19. ;
  20. ; Version:    1.0
  21. ; Date:        June 8, 1988
  22. ;
  23. ; (c) Arun Johary, Bo Ericsson 1988
  24. ;--------------------------------------------------------------------------
  25.  
  26.  
  27. ;------    equates -------------------------------------------------------
  28. TRUE        equ    1
  29. FALSE        equ    0
  30. CR        equ    0dh
  31. LF        equ    0ah
  32. BS        equ    08h
  33. EOS        equ    '$'
  34. ACTIVE        equ    TRUE
  35. INACTIVE    equ    FALSE
  36. LORES        equ    0
  37. HIRES        equ    1
  38. HIDDENMODE    equ    21h
  39.  
  40. CTRLMAKE        equ    01dh
  41. CTRLBREAK        equ    09dh
  42. SETLORES        equ    1
  43. SETLORESMAKE        equ    050h
  44. SETLORESBREAK        equ    0d0h
  45. SETHIRES        equ    2
  46. SETHIRESMAKE        equ    048h
  47. SETHIRESBREAK        equ    0c8h
  48. PANRIGHTONE        equ    3
  49. PANRIGHTONEMAKE        equ    04dh
  50. PANRIGHTONEBREAK    equ    0cdh
  51. PANLEFTONE        equ    4
  52. PANLEFTONEMAKE        equ    04bh
  53. PANLEFTONEBREAK        equ    0cbh
  54.  
  55.  
  56. ;------ externals -----------------------------------------------------
  57. extrn    SetMode:near
  58. extrn    DrawChr:near
  59. extrn    Horiz_Scroll_4:near
  60. extrn    EndOfProgram:byte
  61.  
  62.  
  63. ;------    macros --------------------------------------------------------
  64. pushall    macro
  65.     push    ax
  66.     push    bx
  67.     push    cx
  68.     push    dx
  69.     push    di
  70.     push    si
  71.     push    ds
  72.     push    es
  73.     push    bp
  74.     endm
  75.  
  76. popall    macro
  77.     pop    bp
  78.     pop    es
  79.     pop    ds
  80.     pop    si
  81.     pop    di
  82.     pop    dx
  83.     pop    cx
  84.     pop    bx
  85.     pop    ax
  86.     endm
  87.  
  88.  
  89. ;------    structures ----------------------------------------------------
  90.  
  91.  
  92. ;------ code segment --------------------------------------------------
  93. code segment para public 'code'
  94.     assume cs:code, ds:code, es:code, ss:code
  95.     org    100h
  96. begin:
  97.     jmp    Main
  98.  
  99.  
  100. ;------ data area -----------------------------------------------------
  101. Msg0    db    'VGAZOOM.COM - VGA hidden mode driver - Ver. 1.0', CR, LF
  102.     db    '  Program by Arun Johary and Bo Ericsson', CR, LF, LF, EOS  
  103. Msg1    db    'Program installed', CR, LF, EOS
  104. Msg2    db    'New program did not install', CR, LF, EOS
  105. Msg3    db    'Program already installed', CR, LF, EOS
  106. Msg4    db    'VGA not present. Program did not install', CR, LF, EOS
  107.  
  108. Msg5    db    'To set High resolution (1280x400), press Ctrl Up-Arrow', CR, LF
  109.     db    'To set Low resolution, (640x400) press Ctrl Down-Arrow', CR, LF
  110.     db    'To Pan right in Low resolution, press Ctrl Right-Arrow', CR, LF
  111.     db    'To Pan left in Low resolution, press Ctrl Left-Arrow', CR, LF, LF, EOS
  112.  
  113. Command        db    0
  114. Status        db    HIRES
  115. VideoMode    db    0
  116.  
  117. CtrlStatus        db    FALSE
  118. LoResStatus        db    FALSE
  119. HiResStatus        db    FALSE
  120. PanRightOneStatus    db    FALSE
  121. PanLeftOneStatus    db    FALSE
  122. PanPosition        dw    0
  123.  
  124. ScanCode    db    0
  125.  
  126. MemOffset    dw    00000h
  127. MemSegment    dw    0a000h
  128. FontOffset    dw    0
  129. FontSegment    dw    0
  130.  
  131.  
  132. ;-----------------------------------------------------------------------
  133. Main proc near
  134.  
  135. ;------ are we already installed?
  136.     call    CheckAlreadyInstalled
  137.     jc    MainError
  138.  
  139. ;------ is this a VGA environment?
  140.     mov    ax, 1a00h
  141.     int    10h
  142.     cmp    al, 1ah
  143.     jne    NotVGA
  144.  
  145.     call    SetNewVideoVector
  146.      call    SetNewKeyboardVector
  147.  
  148. ;------ display initial greeting
  149.     mov    ax, HIDDENMODE
  150.     int    10h
  151.     mov    dx, offset Msg0
  152.     mov    ah, 9
  153.     int    21h
  154.     mov    dx, offset Msg1
  155.     mov    ah, 9
  156.     int    21h
  157.     mov    dx, offset Msg5
  158.     mov    ah, 9
  159.     int    21h
  160.  
  161.     call    TerminateButStayResident
  162.  
  163. ;------ TSR failed
  164. MainError:
  165.     mov    ax, HIDDENMODE
  166.     int    10h
  167.     mov    dx, offset Msg0
  168.     mov    ah, 9
  169.     int    21h
  170.     mov    dx, offset Msg3
  171.     mov    ah, 9
  172.     int    21h
  173.     mov    dx, offset Msg2
  174.     mov    ah, 9
  175.     int    21h
  176.     mov    dx, offset Msg5
  177.     mov    ah, 9
  178.     int    21h
  179.     ret
  180.  
  181. ;------ VGA environment not found
  182. NotVGA:
  183.     mov    dx, offset Msg0
  184.     mov    ah, 9
  185.     int    21h
  186.     mov    dx, offset Msg4
  187.     mov    ah, 9
  188.     int    21h
  189.     ret
  190.     
  191.  
  192. Main endp
  193.  
  194.  
  195. ;-----------------------------------------------------------------------
  196. CheckAlreadyInstalled proc near
  197.  
  198. ;------ get video interrupt vector
  199.     mov    ah, 35h            ;get interrupt vector function
  200.     mov    al, 10h            ;vector number
  201.     int    21h            ;execute! (returns es:bx)
  202.     
  203. ;------ look for already-present marker
  204.     cld                ;forward direction
  205.     mov    di, bx
  206.     add    di, Marker-VideoHandler    ;offset to marker string
  207.     mov    si, offset Marker    ;offset to our string
  208.     mov    cx, MarkerEnd-Marker    ;length of string
  209.     repe    cmpsb            ;compare the strings
  210.     jcxz    AlreadyLoaded        ;compare ok, handler already loaded
  211.     jmp    NotAlreadyLoaded    ;compare not ok, handler not there
  212.  
  213. ;------ Program already loaded
  214. AlreadyLoaded:
  215.     stc                ;error= set carry flag
  216.     ret
  217.  
  218. ;------ New installation
  219. NotAlreadyLoaded:
  220.     clc                ;success= cleared carry flag  
  221.     ret
  222.     
  223. CheckAlreadyInstalled endp
  224.  
  225.  
  226. ;-----------------------------------------------------------------------
  227. SetNewVideoVector proc near
  228.  
  229. ;------ get old video interrupt vector
  230.     mov    ah, 35h            ;get interrupt vector function
  231.     mov    al, 10h            ;video vector 
  232.     int    21h            ;execute! (returns es:bx)
  233.  
  234. ;------ and store it
  235.     mov    cs:OldVideoOffs0, bx    ;store offset of old handler
  236.     mov    cs:OldVideoOffs1, bx    ;store offset of old handler
  237.     mov    ax, es
  238.     mov    cs:OldVideoSeg0, ax    ;store segment of old handler
  239.     mov    cs:OldVideoSeg1, ax    ;store segment of old handler
  240.  
  241. ;------ link our handler into the chain 
  242.     mov    ah, 25h            ;set interrupt vector function
  243.     mov    al, 10h            ;interrupt number
  244.     mov    dx, offset VideoHandler ;ds:dx= address to handler
  245.     int    21h            ;execute!
  246.  
  247. ;------ locate 8*8 font in ROM
  248.     mov    ah, 11h
  249.     mov    al, 30h
  250.     mov    bh, 03h
  251.     int    10h
  252.     mov    cs:FontSegment, es
  253.     mov    cs:FontOffset, bp
  254.     ret
  255.  
  256. SetNewVideoVector endp
  257.  
  258.  
  259. ;-----------------------------------------------------------------------
  260. SetNewKeyboardVector proc near
  261.  
  262. ;------ get keyboard interupt vector
  263.     mov    ah, 35h            ; get vector function call
  264.     mov     al, 9h            ; int 9h vector
  265.     int     21h            ; dos call
  266.     mov    ax, es            ; es contains cs
  267.     mov    cs:OldKeyboardSegment, ax ; save cs
  268.     mov    cs:OldKeyboardOffset, bx ; save ip
  269.  
  270. ;------ set new keyboard interupt vector
  271.     push    cs
  272.     pop    ds
  273.     mov    dx,offset KeyboardHandler ; specify offset to keyboard int trap
  274.     mov     ah, 25h            ; set vector function call
  275.     mov    al, 9h            ; int 9h vector
  276.      int     21h            ; dos call
  277.  
  278.     ret
  279.  
  280. SetNewKeyboardVector endp
  281.  
  282.  
  283. ;-----------------------------------------------------------------------
  284. TerminateButStayResident proc near
  285.  
  286.     mov    dx, offset EndOfProgram    ;divide offset of end of program
  287.     mov    cl, 4
  288.     shr    dx, cl            ;by four
  289.     inc    dx            ;and increment result by 1
  290.  
  291.     mov    ah, 31h            ;terminate but stay resident func
  292.     mov    al, 0            ;return code
  293.     int    21h            ;execute
  294.  
  295.     stc                ;could not TSR the program
  296.     ret
  297.  
  298. TerminateButStayResident endp
  299.  
  300.  
  301. ;-----------------------------------------------------------------------
  302. VideoHandler proc far
  303.  
  304. ;------ trap entry to old video handler
  305.     call    PreBios
  306.  
  307. ;------ call old video handler
  308.         pushf
  309. LongCall0    db    09ah        
  310. OldVideoOffs0    dw    0
  311. OldVideoSeg0    dw    0
  312.  
  313. ;------ trap exit from old video handler
  314.     call    PostBios
  315.  
  316. ;------ return to application
  317.     iret
  318.  
  319. Marker        db    'Hidden VGA mode program'
  320. MarkerEnd    label     byte
  321.  
  322. VideoHandler endp
  323.  
  324.  
  325. ;-----------------------------------------------------------------------
  326. PreBios proc near
  327.  
  328.     cmp    ah, 0
  329.     je    PreBiosModeSet
  330.     cmp    ah, 0eh
  331.     je    PreBiosTTYOutput
  332.     cmp    ah, 6
  333.     je    PreBiosScroll
  334.     ret
  335.  
  336. PreBiosModeSet:
  337.     call    HandlePreModeSet
  338.     ret
  339.  
  340. PreBiosTTYOutput:
  341.     call    HandlePreTTYOutput
  342.     ret
  343.  
  344. PreBiosScroll:
  345.     call    HandlePreScroll
  346.     ret
  347.  
  348. PreBios endp
  349.  
  350.  
  351. ;-----------------------------------------------------------------------
  352. HandlePreModeSet proc near
  353.  
  354.     mov    cs:VideoMode, al
  355.     cmp    al, HIDDENMODE
  356.     je    SetHiddenMode
  357.     ret
  358.  
  359. SetHiddenMode:
  360.     pushall
  361.  
  362.     mov    ax, 0eh
  363.         pushf
  364. LongCall1    db    09ah        
  365. OldVideoOffs1    dw    0
  366. OldVideoSeg1    dw    0
  367.  
  368. ;set the hidden mode here
  369.  
  370.     mov    ax, HIRES
  371.     call    SetMode
  372.     mov    cs:Status, HIRES
  373.     mov    ax, 40h
  374.     mov    ds, ax
  375.     mov    bx, 4ah
  376.     mov    [bx], byte ptr 160
  377.     mov    bx, 84h
  378.     mov    [bx], byte ptr 49
  379.     mov    bx, 49h
  380.     mov    [bx], byte ptr HIDDENMODE
  381.     mov    cs:MemOffset, 0
  382.     mov    cs:PanPosition, 0
  383.     popall
  384.     add    sp, 4
  385.     iret
  386.  
  387. HandlePreModeSet endp
  388.  
  389.  
  390. HandlePreScroll proc near
  391.     
  392.     cmp    cs:VideoMode, HIDDENMODE
  393.     je    HiddenScroll
  394.     ret
  395.  
  396. HiddenScroll:
  397.     pushall
  398.     call    ScrollOneLine
  399.     popall
  400.     add    sp, 4
  401.     iret
  402.  
  403. HandlePreScroll endp
  404.  
  405.  
  406. ;-----------------------------------------------------------------------
  407. HandlePreTTYOutput proc near
  408.  
  409.     cmp    cs:VideoMode, HIDDENMODE ;is this a request for a hidden mode
  410.     je    HiddenTTY        ;yes, handle the tty output
  411.     ret
  412.  
  413. HiddenTTY:
  414.     pushall
  415.     call    HandleHiddenTTY
  416.     popall
  417.     add    sp, 4
  418.     iret
  419.  
  420. HandlePreTTYOutput endp
  421.  
  422.  
  423. ;----------------------------------------------------------------------
  424. HandleHiddenTTY proc near
  425.  
  426.     cmp    al, 32
  427.     jl    TTYControlChar
  428.     mov    bx, 160
  429.     mov    dx, 8
  430.     mov    cx, 50
  431.     mov    si, offset MemOffset
  432.     lds    si, cs:[si]
  433.     push    si
  434.     mov    di, offset FontOffset
  435.     les    di, cs:[di]
  436.     call    DrawChr
  437.     pop    si
  438.  
  439.     inc    si
  440.     mov    cs:MemOffset, si
  441.     ret
  442.  
  443. TTYControlChar:
  444.     cmp    al, CR
  445.     jne    TestLF
  446.     call    HandleCR
  447.     ret
  448. TestLF:
  449.     cmp    al, LF
  450.     jne    TestTAB
  451.     call    HandleLF
  452.     ret
  453. TestTAB:
  454.     cmp    al, BS
  455.     jne    HandleTTYEnd
  456.     call    HandleBS
  457.     ret
  458.  
  459. HandleTTYEnd:
  460.     ret
  461.  
  462. HandleHiddenTTY endp
  463.  
  464. HandleCR proc near
  465.  
  466.     int    3
  467.     xor    dx, dx
  468.     mov    ax, cs:MemOffset
  469.     mov    bx, 160
  470.     div    bx
  471.     xor    dx, dx
  472.     mul    bx
  473.     mov    cs:MemOffset, ax
  474.     ret
  475.  
  476. HandleCR endp
  477.  
  478. HandleLF proc near
  479.  
  480.     mov    ax, cs:MemOffset
  481.     add    ax, 160*8
  482.     cmp    ax, 50*8*160
  483.     jb    HandleLF1
  484.     sub    ax, 160*8
  485.     push    ax
  486.     call    ScrollOneLine
  487.     pop    ax
  488.  
  489. HandleLF1:
  490.     mov    cs:MemOffset, ax
  491.     ret
  492.  
  493. HandleLF endp
  494.  
  495. HandleBS proc near
  496.  
  497.     mov    ax, cs:MemOffset
  498.     dec    ax
  499.     mov    cs:MemOffset, ax
  500.     ret
  501.  
  502. HandleBS endp
  503.  
  504. ScrollOneLine proc near
  505.  
  506.     mov    ax, 0a000h
  507.     mov    es, ax
  508.     mov    ds, ax
  509.     xor    di, di
  510.     mov    si, 160*8
  511.     mov    cx, (49*8*160)/2
  512.     cld
  513.     rep    movsw
  514.     mov    cx, (1*8*160)/2
  515.     xor    ax, ax
  516.     rep    stosw
  517.     ret
  518.  
  519. ScrollOneLine endp
  520.  
  521.  
  522. ;----------------------------------------------------------------------
  523. PostBios proc near
  524.  
  525.     ret
  526.  
  527. PostBios endp
  528.  
  529.  
  530. ;------------------------------------------------------------------------
  531. KeyboardHandler proc near
  532.  
  533. ;------ save processor state
  534.     pushall
  535.  
  536. ;------ check if our key combination is pressed
  537.     call    CheckOurKeys
  538.     jnc    Keyboard00
  539.  
  540.     cmp    cs:Command, SETHIRES
  541.     je    HandleSetHires
  542.     cmp    cs:Command, SETLORES
  543.     je    HandleSetLores
  544.     cmp    cs:Command, PANRIGHTONE
  545.     je    HandlePanRightOne
  546.     cmp    cs:Command, PANLEFTONE
  547.     je    HandlePanLeftOne
  548.     jmp    Keyboard00
  549.  
  550. HandleSetLores:
  551.     mov    ax, LORES
  552.     call    SetMode
  553.     mov    cs:Status, LORES
  554.     jmp    Keyboard00
  555.  
  556. HandleSetHires:
  557.     mov    ax, HIRES
  558.     call    SetMode
  559.     mov    cs:Status, HIRES
  560.     jmp    Keyboard00
  561.  
  562. HandlePanRightOne:
  563.     cmp    cs:Status, HIRES
  564.     je    Keyboard00
  565.     cmp    cs:PanPosition, 640
  566.     je    Keyboard00
  567.     mov    ax, 1
  568.     call    Horiz_Scroll_4
  569.     inc    cs:PanPosition
  570.     jmp    Keyboard00
  571.  
  572. HandlePanLeftOne:
  573.     cmp    cs:Status, HIRES
  574.     je    Keyboard00
  575.     cmp    cs:PanPosition, 0
  576.     je    Keyboard00
  577.     mov    ax, -1
  578.     call    Horiz_Scroll_4
  579.     dec    cs:PanPosition
  580.     jmp    Keyboard00
  581.  
  582. ;------ restore processor state
  583. Keyboard00:
  584.     popall
  585.  
  586. ;------ jump to the original keyboard routine
  587. LongJump        db    0eah    
  588. OldKeyboardOffset    dw    0
  589. OldKeyboardSegment    dw    0
  590.  
  591. KeyboardHandler    endp
  592.  
  593.  
  594. ;----------------------------------------------------------------------
  595. CheckOurKeys proc near
  596.  
  597.     int    3
  598.     cmp    cs:VideoMode, HIDDENMODE
  599.     je    ReadInKey
  600.     jmp    KeyNoTest
  601.  
  602. ;------ read in the key from port 60h
  603. ReadInKey:
  604.     mov    dx,60h
  605.     in     al,dx
  606.     mov    cs:ScanCode,al
  607.  
  608. ;------ check the control key
  609.     cmp    al, CTRLMAKE
  610.     jne    Key00
  611.     mov    cs:CtrlStatus, TRUE
  612.     jmp    KeyTest
  613.  
  614. Key00:
  615.     cmp    al, CTRLBREAK
  616.     jne    Key01
  617.     mov    cs:CtrlStatus, FALSE
  618.     jmp    KeyNoTest
  619.  
  620. ;------ check SETLORES KEY
  621. Key01:
  622.     cmp    al, SETLORESMAKE
  623.     jne    Key02
  624.     mov    cs:LoResStatus, TRUE
  625.     jmp    KeyTest
  626. Key02:
  627.     cmp    al, SETLORESBREAK
  628.     jne    Key03
  629.     mov    cs:LoResStatus, FALSE
  630.     jmp    KeyNoTest
  631.  
  632. ;------ check SETHIRES KEY
  633. Key03:
  634.     cmp    al, SETHIRESMAKE
  635.     jne    Key04
  636.     mov    cs:HiResStatus, TRUE
  637.     jmp    KeyTest
  638. Key04:
  639.     cmp    al, SETHIRESBREAK
  640.     jne    Key05
  641.     mov    cs:HiResStatus, FALSE
  642.     jmp    KeyNoTest
  643.  
  644. ;------ check PANRIGHTONE KEY
  645. Key05:
  646.     cmp    al, PANRIGHTONEMAKE
  647.     jne    Key06
  648.     mov    cs:PanRightOneStatus, TRUE
  649.     jmp    KeyTest
  650. Key06:
  651.     cmp    al, PANRIGHTONEBREAK
  652.     jne    Key07
  653.     mov    cs:PanRightOneStatus, FALSE
  654.     jmp    KeyNoTest
  655.  
  656. ;------ check PANLEFTONE KEY
  657. Key07:
  658.     cmp    al, PANLEFTONEMAKE
  659.     jne    Key08
  660.     mov    cs:PanLeftOneStatus, TRUE
  661.     jmp    KeyTest
  662. Key08:
  663.     cmp    al, PANLEFTONEBREAK
  664.     jne    Key09
  665.     mov    cs:PanLeftOneStatus, FALSE
  666.     jmp    KeyNoTest
  667.  
  668. Key09:
  669.     jmp    KeyNoTest
  670.  
  671. ;------ test if any of our combinations are present
  672. KeyTest:
  673.     cmp    cs:CtrlStatus, TRUE
  674.     jne    KeyNoTest
  675.  
  676.     cmp    cs:LoResStatus, TRUE
  677.     jne    KeyTest0
  678.     mov    cs:Command, SETLORES
  679.     jmp    KeyFound
  680. KeyTest0:
  681.     cmp    cs:HiResStatus, TRUE
  682.     jne    KeyTest1
  683.     mov    cs:Command, SETHIRES
  684.     jmp    KeyFound
  685. KeyTest1:
  686.     cmp    cs:PanRightOneStatus, TRUE
  687.     jne    KeyTest2
  688.     mov    cs:Command, PANRIGHTONE
  689.     jmp    KeyFound
  690. KeyTest2:
  691.     cmp    cs:PanLeftOneStatus, TRUE
  692.     jne    KeyTest3
  693.     mov    cs:Command, PANLEFTONE
  694.     jmp    KeyFound
  695. KeyTest3:
  696.  
  697.  
  698.     jmp    KeyNoTest
  699.  
  700. ;------ our key combination is present
  701. KeyFound:
  702.     stc
  703.     ret
  704.  
  705. KeyNoTest:
  706.     clc
  707.     ret
  708. CheckOurKeys endp
  709.  
  710.  
  711. ;----------------------------------------------------------------------
  712. Beep    proc near
  713.  
  714. BEEPFREQ    equ    2000
  715. BEEPLEN        equ    5000
  716. ; ax= frequency of tone
  717.  
  718.     mov    ax, 1000
  719.     call    tone_init
  720.     call    tone_on
  721.     mov    cx, BEEPLEN
  722. shb01:
  723.     loop    shb01
  724.     call    tone_off
  725.     mov    cx, BEEPLEN
  726. shb02:
  727.     loop    shb02
  728.     ret
  729.  
  730. Beep    endp
  731.  
  732.  
  733. ;-----------------------------------------------------------------------
  734. tone_init proc near
  735.  
  736. ;------ frequency in ax
  737.     push    ax
  738.     mov    al,0b6h
  739.     out    43h,al
  740.     pop    ax
  741.  
  742.     mov    bx,ax
  743.     out    42h,al
  744.     jmp    short $+2
  745.     mov    al,bh
  746.     out    42h,al
  747.  
  748.     ret
  749.  
  750. tone_init endp
  751.  
  752.  
  753. ;-----------------------------------------------------------------------
  754. tone_on proc near
  755.  
  756.     in    al,61h
  757.     jmp    short $+2
  758.     jmp    short $+2
  759.     or    al,3
  760.     out    61h,al
  761.  
  762.     ret
  763. tone_on endp
  764.  
  765.  
  766. ;-----------------------------------------------------------------------
  767. tone_off proc near
  768.  
  769.     in    al,61h
  770.     jmp    short $+2
  771.     jmp    short $+2
  772.     and    al,0fch
  773.     out    61h,al
  774.  
  775.     ret
  776. tone_off endp
  777.  
  778.  
  779. ;------    end of module -------------------------------------------------
  780. code ends
  781. end begin
  782.